<script setup>
import {reactive, inject, ref, onMounted, provide, watch} from 'vue'
import { useMessage } from 'jiuqi-ui'
import DimItemEditor from "./DimItemEditor.vue";
import {getTreeNodeById, scrollIntoView} from "../../../../utils/TreeHelper";
import {checkName} from "../../../../utils/LabelCheck";
import IconEnum from "../../../../utils/iconEnum";
import {Debounce} from "../../../../utils/debounce";
//================================================【组件通信】============================================================
//================================================================【接收】
//父组件传递的数据
const props = defineProps({
    isSaveas:{
        type:Boolean,
        required:true
    }
});
//发送请求组件
const context = inject('context')
//控制 标签编辑模态框  显示与隐藏
const modifyLabelVisible = inject('modifyLabelVisible')
//获取 维度编辑模态框  显示与隐藏
const dimItemEditorVisiable = inject('dimItemEditorVisiable')
//获取 当前编辑或修改的 标签数据
const labelItem = inject('curLabelItem')
//获取 当前标签分组对应的 子组件处理后 需要触发的回调
const {callback} = inject('labelFolder')
//================================================================【发送】
//当 取值方式 为 指定数据项 时，获取的维度项数组（维度项编码、维度项名称）
const dimItemArr = reactive([])
provide('modifyDimItemArr',dimItemArr)

//控制 标签编辑模态框（当前模态框） 显示与隐藏
provide('modifyLabelVisible',modifyLabelVisible)
//================================================【公用相关】============================================================
//提示信息组件
const message = useMessage()

//================================================【组件属性】============================================================
watch(()=>labelItem.dimCode,()=>{
    labelItem.dimItemCodes = ''
    dimItemArr.length = 0
},{deep:true})
// 标签标识 自动转为大写
watch(()=>labelItem.name,(newValue)=>{
    if (newValue !== '') {
        labelItem.name = labelItem.name.toUpperCase()
    }
},{deep:true})
//================================================【普通方法】============================================================
//==================================================================【表单相关】
//表单ref
const labelForm = ref(null)
const rules = {
    name:[{
        required: true,
        message: '请输入代码'
    },{
        asyncValidator: (rule, value) => {
            return new Promise((resolve, reject) => {
                if (value.length > 50) {
                    reject('代码长度不能超过50个字符')
                } else if (!/^[a-zA-Z][\w]*$/.test(value)){
                    reject("代码只能由字母、数字和_组成,并且以字母开头")
                }else if (/\.$/.test(value)) {
                    reject('代码不能以.结尾')
                } else if (/[/\\*<>"'\\|?:]/.test(value)) {
                    reject('代码不能包含\\ 、/ 、: 、* 、? 、" 、\' 、< 、> 、|中任意字符')
                } else {
                    checkName(context,labelItem).then(()=>{
                        resolve()
                    }).catch((errorMsg)=>{
                        reject(errorMsg)
                    })
                }
            })
        }
    }],
    title: [
        {
            required: true,
            message: '请输入名称'
        }, {
            asyncValidator: (rule, value) => {
                return new Promise((resolve, reject) => {
                    if (value.length > 50) {
                        reject('名称长度不能超过50个字符')
                    } else if (/\.$/.test(value)) {
                        reject('名称不能以.结尾')
                    } else if (/[/\\*<>"'\\|?:]/.test(value)) {
                        reject('名称不能包含\\ 、/ 、: 、* 、? 、" 、\' 、< 、> 、|中任意字符')
                    } else {
                        resolve()
                    }
                })
            }
        }
    ],
    belongLabelFolder:[{
        asyncValidator: () => {
            return new Promise((resolve, reject) => {
                if (labelItem.pId === '') {
                    reject('请选择所属分组')
                } else {
                    resolve()
                }
            })
        }
    }],
    dimCode:[{
        asyncValidator: () => {
            return new Promise((resolve, reject) => {
                // 编辑（移动分组）模式下校验
                if (labelItem.dimCode === '') {
                    reject('请选择基础数据')
                } else {
                    resolve()
                }
            })
        }
    }],
    //维度项 或 表达式 校验（先校验；校验后，formulaData 或 dimItemArr 存入 dimItemCodes）
    dimItemOrFormula:[{
        asyncValidator: () => {
            return new Promise((resolve, reject) => {
                if (labelItem.isFormula) {
                    if (labelItem.formulaData === ''){
                        reject('请输入表达式')
                    }else {
                        labelItem.dimItemCodes = labelItem.formulaData
                        resolve()
                    }
                }else {
                    if (dimItemArr.length === 0) {
                        reject('请选择维度项')
                    }else {
                        labelItem.dimItemCodes = ''
                        for (let i = 0; i < dimItemArr.length; i++) {
                            if (i !== dimItemArr.length - 1){
                                labelItem.dimItemCodes = labelItem.dimItemCodes + dimItemArr[i].dimItemCode + ','
                            }else {
                                labelItem.dimItemCodes += dimItemArr[i].dimItemCode
                            }
                        }
                        if (labelItem.dimItemCodes.length > 4000)
                            reject('维度项长度不能超过4000')
                        else
                            resolve()
                    }
                }
            })
        }
    }]
}
//==================================================================【树形相关】
//=========================================【标签分组】
//所属标签分组 的 溯源标签代码路径
const folderTracePath  = reactive([])
//所属标签分组树形数据
const belongLabelFolderTreeData = reactive([])
//原有所属标签分组树形展示数据副本
const preBelongLabelFolderTreeData = reactive([])
//所属标签分组树形是否处于搜索状态
const isBelongLabelFolderSearching = ref(false)
//选中标签分组树形数据
let selectedFolderNode = reactive({})
//后期 点击非默认节点后  默认节点需要取消选择状态
const defaultSeletedFolderNode = ref(null)
//获取标签分组树形根节点
function getFolderTreeRootNode() {
    return new Promise((resolve) => {
        context.getPlugin('http').get("labelmanager/label/group/tree?pId=").then((res) => {
            belongLabelFolderTreeData.splice(0,belongLabelFolderTreeData.length,...res.data)
            resolve()
        });
    });
}
//异步加载树形数据  逐级获取  所属标签分组
function loadFolderTreeData(item, pathIndex) {
    return new Promise((resolve) => {
        if (item.expand) {
            return
        } else {
            context.getPlugin('http').get(`labelmanager/label/group/tree?pId=${item.id}`).then(({data}) => {
                const nodeDataArr = []
                if (data.length === 0) {
                    item.expand = true
                }
                for (let i = 0; i < data.length; i++) {
                    const nodeData = data[i];
                    // 叶子节点
                    if (nodeData.isLeaf) {
                        nodeData.expand = true
                    } else {
                        nodeData.loading = false
                        nodeData.expand = false
                    }
                    //如果是"基础数据"节点,不能选择
                    if (nodeData.id === 'JIUQI_BASEDATA_LABEL'){
                        nodeData.disabled = true
                    }
                    nodeDataArr.push(nodeData)
                }

              //模态框中的树形加载  start
              let treeNodeById = getTreeNodeById(belongLabelFolderTreeData, item.id)
              if (!treeNodeById.children) treeNodeById.children = reactive([])
              treeNodeById.children.push(...nodeDataArr)
              resolve(nodeDataArr)
              //模态框中的树形加载  end
              treeNodeById.expand = true
                if (pathIndex !== undefined) {
                    expandFolderPath(pathIndex + 1)
                }
            })
        }
    })
}
function expandFolderPath(pathIndex) {
    // 不存在路径信息，则不执行
    if(!folderTracePath){
        return
    }
    if(pathIndex < folderTracePath.length-1){
        const nodeId = folderTracePath[pathIndex]
        const targetNode = getTreeNodeById(belongLabelFolderTreeData,nodeId)
        if(targetNode){
            loadFolderTreeData(targetNode,pathIndex)
        }
    }else{
        const nodeId = folderTracePath[pathIndex]
        if(nodeId){
            const targetNode =getTreeNodeById(belongLabelFolderTreeData,nodeId)
            if(targetNode){
                targetNode.selected =true
                targetNode.belongLabelFolderSelected = true
                selectedFolderNode.title = targetNode.title
                defaultSeletedFolderNode.value = targetNode
            }
        }
    }
}
//选择树形节点
function folderNodeSelected(node) {
    if( defaultSeletedFolderNode.value){
        defaultSeletedFolderNode.value.selected =false
        defaultSeletedFolderNode.value = null
    }
    if (node.selected){
        labelItem.pId = node.id
        node.belongLabelFolderSelected = true
    }

}

//对 所属标签分组树形 进行模糊搜索
function belongLabelFolderTreeSearch(searchValue){
    if (searchValue !== ''){
        if (!isBelongLabelFolderSearching.value) {
            preBelongLabelFolderTreeData.splice(0,preBelongLabelFolderTreeData.length,...belongLabelFolderTreeData)
            isBelongLabelFolderSearching.value = true
        }
        return new Promise((resolve) => {
            Debounce(  context.getPlugin('http').get('labelmanager/label/group/fuzzyMatch?keyWord='+searchValue).then((res) => {
              belongLabelFolderTreeData.splice(
                  0,
                  belongLabelFolderTreeData.length,
                  ...res.data.map(item => ({...item, isLeaf: undefined})));
                resolve()
            }),300)
        })
    }else {
        return new Promise((resolve) => {
          //对于输入中文的场景，当中文还未输入完成（输入框中还是拼音时）也会触发搜索，此时不替换显示数据（因为此时副本还没有填充数据）
            if (preBelongLabelFolderTreeData.length !== 0)
                belongLabelFolderTreeData.splice(0,belongLabelFolderTreeData.length,...preBelongLabelFolderTreeData)

            isBelongLabelFolderSearching.value = false
            resolve()
        })
    }
}
//=========================================【维度】
//关联基础数据（维度） 的 溯源维度编码路径
const dimTracePath  = reactive([])
//关联基础数据（维度）树形数据
const dimTreeData = reactive([])
//原有维度树形展示数据副本
const preDimTreeData = reactive([])
//维度树形是否处于搜索状态
const isDimSearching = ref(false)
//选中维度树形数据
let selectedDimNode = reactive({})
//异步加载树形数据  逐级获取  维度
function loadDimTreeData(item, pathIndex) {

    return new Promise((resolve) => {
        if (item.expand) {
            return
        } else {
            context.getPlugin('http').get(`labelmanager/dimension/getChildren?parentName=${item.id}`).then((res) => {
                const nodeDataArr = []
                const dimarr = res.data
                if (dimarr.length === 0) {
                    item.expand = true
                }
                for (let i = 0; i < dimarr.length; i++) {
                    const nodeData = dimarr[i];
                    // 叶子节点
                    if (nodeData.isLeaf) {
                        nodeData.expand = true
                    } else {
                        nodeData.disabled = true
                        nodeData.loading = false
                        nodeData.expand = false
                    }
                    nodeDataArr.push(nodeData)
                }

                //模态框中的树形加载  start
              let treeNodeById = getTreeNodeById(dimTreeData, item.id)
              if (!treeNodeById.children) treeNodeById.children = reactive([])
              treeNodeById.children.push(...nodeDataArr)
              resolve(nodeDataArr)
              //模态框中的树形加载  end
              treeNodeById.expand = true
                if (pathIndex !== undefined) {
                    expandDimPath(pathIndex + 1)
                }
            })
        }
    })

}
//后期 点击非默认节点后  默认节点需要取消选择状态
const defaultSeletedDimNode = ref(null)
//按路径展开
function expandDimPath(pathIndex){
    // 不存在路径信息，则不执行
    if(!dimTracePath){
        return
    }
    if(pathIndex < dimTracePath.length-1){
        const nodeId = dimTracePath[pathIndex]
        const targetNode = getTreeNodeById(dimTreeData,nodeId)
        if(targetNode){
            loadDimTreeData(targetNode,pathIndex)
        }
    }else{
        const nodeId = dimTracePath[pathIndex]
        if(nodeId){
            const targetNode =getTreeNodeById(dimTreeData,nodeId)
            if(targetNode){
                targetNode.selected =true
                targetNode.dimCodeSelected = true
                selectedDimNode.title = targetNode.title
                defaultSeletedDimNode.value = targetNode
            }
        }
    }
}
//选择树形节点
function dimNodeSelected(node) {
    if( defaultSeletedDimNode.value){
        defaultSeletedDimNode.value.selected =false
        defaultSeletedDimNode.value = null
    }
    if (node.selected){
        labelItem.dimCode = node.id;
        node.dimCodeSelected = true
    }
}

//对 维度树形 进行模糊搜索
function dimTreeSearch(searchValue) {
    if (searchValue !== ''){
        if (!isDimSearching.value) {
            preDimTreeData.splice(0,preDimTreeData.length,...dimTreeData)
            isDimSearching.value = true
        }
        return new Promise((resolve) => {
            Debounce(  context.getPlugin('http').get('labelmanager/dimension/fuzzyMatch?keyWord='+searchValue).then((res) => {
              dimTreeData.splice(
                  0,
                  dimTreeData.length,
                  ...res.data.map(item => ({...item, isLeaf: undefined})));
                resolve()
            }),300)
        })
    }else {
        return new Promise((resolve) => {
          //对于输入中文的场景，当中文还未输入完成（输入框中还是拼音时）也会触发搜索，此时不替换显示数据（因为此时副本还没有填充数据）
            if (preDimTreeData.length !== 0)
              dimTreeData.splice(0,dimTreeData.length,...preDimTreeData)

            isDimSearching.value = false
            resolve()
        })
    }
}
//==================================================================【选择维度项】
function addDimItem(){
    // console.log(labelItem.isFormula)
    dimItemEditorVisiable.value = true
}
//==================================================================【模态框：取消、确认】
function cancel() {
    modifyLabelVisible.value = false
}
const confirmLoading = ref(false)
function confirm() {
    if(confirmLoading.value){
        return;
    }
    confirmLoading.value = true
    labelForm.value.validate().then(res => {
        if (res == null) {
            context.getPlugin("http").post("labelmanager/label/save", labelItem).then(() => {
                callback.saveLabelBack()
                modifyLabelVisible.value = false
                confirmLoading.value = false
            }).catch(() =>{
                message.error('标签编辑失败')
                confirmLoading.value = false
            })
        }else{
            confirmLoading.value = false
        }
    })
}
//================================================【生命周期】============================================================
onMounted(() => {

    //获取 标签分组树形数据
    getFolderTreeRootNode().then(() => {
        //获取 标签分组溯源路径
        context.getPlugin('http').get(`labelmanager/label/group/getTracePath/${labelItem.type}/${labelItem.pId}`).then(({data}) => {
            folderTracePath.splice(0, folderTracePath.length, ...data)
            expandFolderPath(0)
        })
    }).catch(() => {
        message.error('获取标签分组溯源路径失败')
    })

    //获取 基础数据维度树形数据
    context.getPlugin('http').get('labelmanager/dimension/getChildren?parentName=').then((res) => {
        dimTreeData.splice(0, dimTreeData.length, ...res.data)
        //非叶子节点设置不可选中
        for (let dimTreeDatum of dimTreeData) {
            if (!dimTreeDatum.isLeaf)
                dimTreeDatum.disabled = true
        }
        //查询 已选择维度  的溯源路径
        context.getPlugin('http').get(`labelmanager/dimension/getTracePath/${labelItem.dimCode}`)
            .then((res) => {
                dimTracePath.splice(0,dimTracePath.length,...res.data)
                expandDimPath(0)
            }).catch(() => {
            message.error('获取维度溯源路径失败')
        })
    })


    if (labelItem.isFormula){
        // selectedOption.value = '1'
    }else {
        // selectedOption.value = '0'
        //查询 已选择维度项  的维度名称
        context.getPlugin('http').post(`labelmanager/dimension/member/byDimMemberCodes/${labelItem.dimCode}`,labelItem.dimItemCodes.split(','))
            .then((res) => {
                dimItemArr.length = 0
                const dimMemberList = res.data
                for (const dimMemberListElement of dimMemberList) {
                    const {code:dimItemCode,name:dimItemName} = dimMemberListElement
                    dimItemArr.push({dimItemCode,dimItemName})
                }
            }).catch(() => {
            message.error('获取已选择维度项名称失败')
        })
    }


})
</script>

<template>
  <j-modal
          v-model="modifyLabelVisible"
          :title="props.isSaveas ? '复制标签' : '编辑标签'"
          :fullscreenable='false'
          :closable="!confirmLoading"
          :mask-closable="false"
          :mask="false"
  >
      <j-modal-content class="modalContent" >
          <j-form ref="labelForm" :model="labelItem" label-position="right" :label-width="80" :rules="rules">
              <j-form-item label="代码" prop="name" required>
                  <j-input v-model="labelItem.name" placeholder="请输入代码" class="input-toupper" name="upper" long :disabled="!props.isSaveas"></j-input>
              </j-form-item>
              <j-form-item label="名称" prop="title" required>
                  <j-input v-model="labelItem.title" placeholder="请输入名称" long></j-input>
              </j-form-item>
              <j-form-item label="所属分组" prop="belongLabelFolder" required>
                  <j-tree-select
                      :tree-data="belongLabelFolderTreeData"
                      :load-data="loadFolderTreeData"
                      v-model="selectedFolderNode"
                      :search="true"
                      :search-method="belongLabelFolderTreeSearch"
                      @change="folderNodeSelected"
                      @visible="scrollIntoView('belongLabelFolderSelected')"
                      placeholder="请选择所属分组"
                      :multiple="false">
                      <template #node="{ title,belongLabelFolderSelected}">
                          <j-space :size="8">
                              <span :class=" 'nvwa-iconfont' + IconEnum.notLeaf"></span>
                              <span :class="belongLabelFolderSelected? ' belongLabelFolderSelected':''">{{ title }}</span>
                          </j-space>
                      </template>
                  </j-tree-select>
              </j-form-item>
              <j-form-item label="基础数据" prop="dimCode" required>
                  <j-tree-select
                          :tree-data="dimTreeData"
                          :load-data="loadDimTreeData"
                          v-model="selectedDimNode"
                          :search="true"
                          :search-method="dimTreeSearch"
                          @change="dimNodeSelected"
                          @visible="scrollIntoView('dimCodeSelected')"
                          placeholder="请选择关联基础数据"
                          :multiple="false"
                  >
                      <template #node="{ id,title,isLeaf,dimCodeSelected }">
                          <div v-if="isLeaf">
                              <j-space :size="8">
                                  <span :class=" 'nvwa-iconfont' + IconEnum.isLeaf"></span>
                                  <span :class="dimCodeSelected?' dimCodeSelected':''">{{ id+' | '+title }}</span>
                              </j-space>
                          </div>
                          <div v-else>
                              <j-space :size="8">
                                  <span :class=" 'nvwa-iconfont' + IconEnum.notLeaf"></span>
                                  <span>{{ id+' | '+title }}</span>
                              </j-space>
                          </div>
                      </template>
                  </j-tree-select>
              </j-form-item>
              <j-form-item label="基础数据项" prop="dimItemOrFormula" v-if="!labelItem.isFormula" required>
                  已选择 {{ dimItemArr.length }}项
                  <j-button style="margin-left: 15px" @click.prevent="addDimItem">选择</j-button>
              </j-form-item>
          </j-form>
      </j-modal-content>
      <template #footer>
              <j-space style="justify-content: flex-end">
                  <j-button @click="cancel">取消</j-button>
                  <j-button type="primary" :loading="confirmLoading" @click="confirm">确定</j-button>
              </j-space>
      </template>
  </j-modal>
    <DimItemEditor
            v-if="dimItemEditorVisiable"
            :process-type="1"
            :selected-dim-name="labelItem.dimCode"
    >
    </DimItemEditor>
</template>
<style scoped>
.modalContent{
    height: 286px !important;
    padding: 16px 24px 16px 10px;
}
.input-toupper input{
  text-transform: uppercase;
}
</style>
